classdef instance_max    < handle
    properties
        samplingTime = 60;
        m_utilization, m_servers, m_num_users;
        price_per_vm_hour;
        vm_instantiation_time;
        t=1;  dt=2;  n=3;
        price = [4 5
                     1 2
                     2 3
                     10 10];
    end
    
    methods
        function obj=instance_max
            obj.samplingTime = 60;
            obj.price_per_vm_hour=0.08; %dollars
            obj.vm_instantiation_time=8;  %minutes
        end
        
        % servers variable is a sequence over an interval of minute unit
        % we are going to sweep through the time
        function servers=per_hour_cost_filter(obj,servers_)
            % servers = [ones(1,45) 2.*ones(1,20)];
            servers=[0 servers_ zeros(1,60)];
            T =size(servers , 2);
            for t=1:T+60
                if (t<T && servers(t+1)>servers(t)) %any time there is a scaleup
                    disp('hi')
                    % make sure the result of scaleup is accounted for, for 60 minutes
                    servers(t+1:t+60) = max(servers(t+1:t+60),servers(t+1));
                end
            end
        end
        
        function cost_=cost(obj,servers_)
            hours=(sum(obj.per_hour_cost_filter(servers_))/60);
            cost_ = hours * obj.price_per_vm_hour;
        end
             
        function m=breakT(obj,m,row)
            a=m(row,:);
            tmp=rand*a(obj.dt);
            m_plus=[a(obj.t)             tmp                 a(obj.n)
                a(obj.t)+tmp        a(obj.dt)-tmp  a(obj.n)];
            m=vertcat(obj.deleteRow(m,row)  , m_plus);
        end
        
        function m=breakN(obj,m,row) 
            a=m(row,:);
            tmp=rand*a(obj.n);
            m_plus=[a(obj.t)       a(obj.dt)   tmp
                a(obj.t)        a(obj.dt)   a(obj.n)-tmp];
            m=vertcat(obj.deleteRow(m,row)  , m_plus);
        end
        
        function n=deleteRow(obj,m,row)
            s=size(m);
            n=zeros(s(1)-1,s(2));
            n(1:row,:)=m(1:row,:);
            n(row:s(1)-1,:)=m(row+1:s(1),:);
        end
        
        function d=indexof(obj,t)
            d=t+1;
        end
        
        function s=cumsumfunc(obj,m)
            s=zeros(1,max(m(:,obj.t)+m(:,obj.dt))); 
            for i=1:size(m,1)
                s(1,obj.indexof(m(i,obj.t)) : obj.indexof(m(i,obj.t)+m(i,obj.dt))-1)=...
                    s(1, obj.indexof(m(i,obj.t)):obj.indexof(m(i,obj.t)+m(i,obj.dt))-1)+m(i,obj.n);
            end            
        end
        
        function is=covers(obj,a,b)
            is=isempty(find(a-b<0,1));
        end
        
        function [mm,grand_tot_cost]=tot_cost(obj,m)
            mm=[];
            grand_tot_cost=0;
            for k=1:size(m,1)
                quantity=m(k,obj.n);               
                tot_cost=[ceil(quantity./obj.price(:,1)), ...                    % price(:,1) is units                
                    ceil(quantity./obj.price(:,1)) .* obj.price(:,2)]; 
                [i j]=find(tot_cost(:,2)==min(tot_cost(:,2))); % i becomes cost minimizing instance type
                first_match = i(1);
                mm = vertcat(mm, [m(k,obj.t) m(k,obj.dt)...
                    first_match  tot_cost(first_match,1)]); % t dt instance_type  number_of_units
                grand_tot_cost = grand_tot_cost + tot_cost(first_match,2);
            end            
        end

        function test(obj)
                m= draw_result().load_data('data/day42_per_min.txt');
                
                header = {'month' 'day' 'hour' 'minute' 'reqnum'};
                g=struct('month', 1 ,'day', 2,'hour', 3,'minute', 4,'reqnum', 5)
                u=UtilityLib();
                between = (1 : 23 *60);
                pu = 14*m(: ,g.reqnum)/max(m(: ,g.reqnum));
                plot(pu);                
                title('Number of users over time');
                xlabel('Time(minutes)');
                ylabel('Number of users');

        end
        
        function all(obj)
            % pu = [10 40 70 20 70 50 60 80 80 60 30];
            pu= sin([1:300]/10)*100+400;
            
            
           
            
            m=[0 size(pu,2) max(pu)];   %t dt n                     
            m_tmp=[];
            grand_tot_cost=Inf;
            for i=1:10
                action = ceil(rand*3)                
                if action==1 
                    row = ceil(rand*size(m,1));
                    disp(strcat('breakN ',num2str(row)));
                    m_tmp=obj.breakN(m,row);
                elseif action==2 
                    row = ceil(rand*size(m,1));
                    disp(strcat('breakT ',num2str(row)));
                    m_tmp=obj.breakT(m,row); 
                elseif action==3
                    row = ceil(rand*size(m,1));
                    disp(strcat('delete ',num2str(row)));
                    m_tmp=obj.deleteRow(m,row);
                end
                m_tmp

                if obj.covers(obj.cumsumfunc(m_tmp),pu) % curve is satisfied
                    [mm_tmp,grand_tot_cost_tmp]=tot_cost(obj,m_tmp);
                    m=m_tmp;
                    if grand_tot_cost_tmp<grand_tot_cost 
                        mm=mm_tmp;
                        grand_tot_cost=grand_tot_cost_tmp;
                    end
                    
                end
                mm
                m
                grand_tot_cost
                
            end
            
            % obj.cumsumfunc(m)
            res=[mm(:,1) mm(:,2) obj.price(mm(:,3),1).*mm(:,4)]
            plot(1:size(pu,2),pu,'--rs',... %  1:size(pu,2),obj.cumsumfunc(res),'-m',...
                    1:size(pu,2),obj.cumsumfunc(m),'.-k'           );
     %        plot(1:size(pu,2),pu,'--rs',1:size(pu,2),obj.cumsumfunc(m));
           
%            pu
%             if obj.covers(obj.cumsumfunc(m),pu) 
%                 disp('covers');
%             end
%             
            % obj.breakT([0 5 5],1)
          %  obj.breakN([0 5 5],1)
           
            
            %------------------------------
            
            
            
            %--------------------------------
            % curve=sum(a);
            % cost=sum(sum(a,2))

            
            % it follows a path of the lowest known cost, keeping a sorted
            % priority queue of alternate path segments along the way
            
%             
%             a=[0 5 5]                 

        end
    end %methods
end %class